package com.piggy.common.netty.ws.server;

import com.piggy.common.netty.ws.handler.HandlerHelper;
import com.piggy.common.netty.ws.session.WsSession;
import com.piggy.netty.ws.annotation.*;
import com.piggy.netty.ws.pojo.Session;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;

import java.io.IOException;
import java.util.Map;

@ConditionalOnProperty(name = "spring.netty.ws")
@ServerEndpoint(value = "${spring.netty.ws.path}", port = "${spring.netty.ws.port}",
        workerLoopGroupThreads = "${spring.netty.ws.workerThread}",
        bossLoopGroupThreads = "${spring.netty.ws.bossThread}",
        allIdleTimeSeconds = "${spring.netty.ws.idleTime:60}"
)
@Slf4j
public class NettyServer {

    @BeforeHandshake
    public void handshake(Session session, @PathVariable("sid") String sid, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Handshake, sid, new WsSession().
                    setSession(session).
                    setSid(sid).
                    setHeaders(headers).setReqMap(reqMap).setPathMap(pathMap));
        });
    }

    @OnOpen
    public void onOpen(Session session, @PathVariable("sid") String sid, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Open, sid, new WsSession().
                    setSession(session).
                    setSid(sid).
                    setHeaders(headers).setReqMap(reqMap).setPathMap(pathMap));
        });
    }

    @OnClose
    public void onClose(@PathVariable("sid") String sid, Session session) throws IOException {
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Close, sid, new WsSession().
                    setSession(session).
                    setSid(sid));
        });
    }

    @OnError
    public void onError(@PathVariable("sid") String sid, Session session, Throwable throwable) {
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Error, sid, new WsSession().
                    setSession(session).
                    setSid(sid));
        });
    }

    @OnMessage
    public void onMessage(@PathVariable("sid") String sid, Session session, String message) {
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Message, sid, new WsSession().
                    setSession(session).
                    setSid(sid).setMessage(message));
        });
    }

    @OnBinary
    public void onBinary(@PathVariable("sid") String sid, Session session, byte[] bytes) {
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Binary, sid, new WsSession().
                    setSession(session).
                    setSid(sid).setBytes(bytes));
        });
    }

    @OnEvent
    public void onEvent(@PathVariable("sid") String sid, Session session, Object evt) {
        HandlerHelper.get().forEach(t-> {
            t.process(WsReqType.Event, sid, new WsSession().
                    setSession(session).
                    setSid(sid).setEvent((IdleStateEvent) evt));
        });
    }
}
